#ifndef LIB_H
#define LIB_H 1

#include <string>
#include <iomanip>
#include <vector>

/** @addtogroup Utilitaires
 *  @{
 */

using namespace std;

/** @brief Effectue \f$a^b\f$.
 *
 * Cette fonction est nécessaire pour élever un entier à une puissance entière,
 * car la STL définit power pour float et double.
 *
 * La fonction est récursive, mais optimisée pour réduire le nombre d'appel :
 * pour calculer la valeur voulue, on utilise \f$a^n = \left( a^2 \right)^{
 * \tfrac{n}{2} } \f$.
 *
 * @param[in] a mantisse.
 * @param[in] b exposant.
 *
 * @return \f$a^b\f$.
 */
int puissance( const int& a, const unsigned& b );

/** @brief Retourne le digit désiré d'un nombre.
 *
 * La fonction extrait le chiffre @f$ b @f$ d'un nombre @f$ a @f$. On commence
 * par faire une division entière, puis on prend le modulo (pour avoir le digit
 * voulu), de la manière suivante : \f$ \tfrac{ a }{ 10^b } \mod 10 \f$.
 *
 * @Warning Le premier digit à droite (LSB) est le digit 0!
 *
 * @param[in] a le nombre.
 * @param[in] b le digit.
 *
 * @return le chiffre voulu.
 */
unsigned digit( const int& a, const int& b );

/** @brief Demande à l'utilisateur d'entrer un nombre.
 *
 * Cette fonction demande à l'utilisateur d'entrer un nombre entier et vérifie
 * que la saisie est valide. Si la saisie est erronée, il est demandé à
 * l'utilisateur d'entrer un nombre valide.
 *
 * @param[in] question demande quoi entrer.
 *
 * @return le nombre entré.
 */
unsigned demanderUnsigned( const string& question );

/** @brief Demande à l'utilisateur d'entrer un nombre dans un intervalle donné.
 *
 * Demande à l'utilisateur d'entrer un nombre entier et vérifie que la saisie
 * est valide. Si la saisie est erronée, l'utilisateur est demandé d'entrer un
 * nombre valide. Ce nombre est en plus borné.
 *
 * On fait simplement appel à demanderUnsigned tant que le résultat n'est pas
 * dans l'intervalle désiré.
 *
 * @param[in] question demande quoi entrer.
 * @param[in] min la borne inférieure.
 * @param[in] max la borne supérieure.
 *
 * @return le nombre entré.
 */
unsigned demanderUnsignedBorne( const string& question,
                                const unsigned& min,
                                const unsigned& max );

/** @brief Affiche les accents des sphères et écoles de magie.
 *
 * Permet d'obtenir le nom des écoles de magie et sphères sous une forme
 * lisible, au lieu de la syntaxe LaTeX utilisée dans le stockage.
 *
 * Gère les "é", "à" et "ô" uniquement pour l'instant, car les autres lettres
 * accentuées ne sont pas utilisées.
 *
 * @deprecated Cette fonction ne devrait plus être utilisée car la gestion des
 * noms des écoles a changé.
 *
 * @b Exemple : "Alt\\'eration" devient "Altération".
 *
 * Le niveau de sortie est paramétré par Debug::itsLevel :\n
 * \e FUNC affiche le message de début et fin d'exécution.\n
 * \e LFUNC permet d'afficher chaque étape.
 *
 * @param[in] brut la string originale.
 *
 * @return la string contenant des accents lisibles.
 */
string afficheAccent( const string& brut );

/** @brief Vérifie si une valeur est déjà présente dans une vecteur.
 *
 * Cette fonction vérifie si une valeur est déjà dans un vecteur. Sert lors du
 * choix d'une compétence, d'un sort, ...
 *
 * Si valeur est déjà présent dans le vecteur adressé par ptr, le résultat sera
 * @c true, et on saura qu'il ne faut pas ajoutter la compétence, sort,...
 *
 * Le niveau de sortie est paramétré par Debug::itsLevel :\n
 * - \e FUNC affiche les messages de début et de fin de méthode.\n
 * - \e DEBUG affiche la position où l'élément a été trouvé.
 *
 * @param[in] ptr pointeur sur le vecteur à vérifier.
 * @param[in] valeur valeur à ajouter.
 *
 * @retval true si la valeur est déjà présente et donc que l'ajout est
 * interdit, @retval false si la valeur n'est pas présente et que l'ajout est
 * autorisé.
 */
bool safePushBack( vector< unsigned > *ptr, const unsigned& valeur );

/** @brief Vérifie si une valeur est déjà présente dans une vecteur, en sautant
 * des position prédéfinies.
 *
 * Vérifie si une valeur est déjà dans un vecteur. Sert lors du choix d'une
 * compétence, sans tenir compte des pourcentages associés à certaines
 * compétences.
 *
 * Si valeur est présent dans le vecteur adressé par ptr mais pas dans sauter,
 * alors le résultat sera \c true. Par contre, si valeur est présent à la fois
 * dans ptr et sauter, alors on n'en tient pas compte et le résultat est \c
 * false.
 *
 * Le niveau de sortie est paramétré par Debug::itsLevel :\n
 * - \e FUNC affiche les messages de début et de fin de méthode.\n
 * - \e DEBUG affiche l'élément à trouver et sa position.
 *
 * @param[in] ptr pointeur sur le vecteur à vérifier.
 * @param[in] valeur valeur à ajouter.
 * @param[in] sauter vecteur des emplacements à ne pas vérifier.
 *
 * @retval true si la valeur est déjà présente et donc que l'ajout est
 * interdit, @retval false si la valeur n'est pas présente et que l'ajout est
 * autorisé.
 */
bool safePushBack( vector<unsigned> *ptr, const unsigned& valeur,
                   vector<unsigned>& sauter );

/** @brief Retranscrit les arguments du programme principal pour gérer les noms
 * composés.
 *
 * Comme on sait que les arguments du programme principal sont Nom
 * Race Classe(s), on va concaténer les arguments qui ne sont pas des
 * nombres.
 *
 * Le niveau de sortie est paramétré par Debug::itsLevel :\n
 * - \e FUNC affiche les messages de début et de fin de méthode.\n
 * - \e DEBUG affiche la ligne d'argument originale, puis les
 * éventuelles fusions.
 *
 * @todo Implémenter une classe du style ArgParser, qui permettrait de gérer
 * mieux les arguments.
 *
 * @param[in] tab arguments originaux.
 * @param[in,out] nbr dimension du tableau.
 * @param[out] retour conteneur des nouveaux arguments, modifié dans
 * la fonction.
 *
 * @return nombre de nouveaux arguments.
 */
void gererEspacesBlancs( char* tab[], int& nbr, vector<string>& retour );

/** @brief Permet de lire un vecteur d'entiers non signés depuis une chaîne de
 * caractères.
 *
 * On parcours alors la chaîne de catactères et on récupère les sous-chaînes
 * qui sont séparées par des espaces. On lit ensuite la valeur en appelent
 * lireString et on stocke le résultat dans le conteneur de sortie si la
 * lecture se fait sans erreur.
 *
 * Le niveau de sortie est paramétré par Debug::itsLevel :\n
 *   - \e FUNC affiche les messages de début et de fin de méthode.\n
 *   - \e LINFO affiche la chaîne de caractère originale et chaque valeur
 * individuelle à convertir.
 *
 * @param[in] donnees chaîne de caractères à "lire".
 * @param[out] vec pointeur sur le conteneur dans lequel seront
 * stockées les valeurs.
 *
 * @retval true si tout s'est bien passé, @retval false sinon, ce qui
 * signifie qu'une conversion en @c unsigned s'est mal déroulée.
 */
bool lireVectorUInt( const string& donnees, vector< unsigned> *vec );

/** @brief Permet de déterminer les ajustement aux talents de voleur.
 *
 * Cette fonction permet de déterminer les ajustements aux talents de voleurs.
 * Sert bien évidemment à la création d'un Voleur, mais aussi d'un Barde et
 * pour les Mage et Clerc ayant des talent de voleur.
 *
 * @param[in] race nom de la Race.
 * @param[in] dext valeur du trait Dexterité.
 * @param[out] ptr pointeur sur le conteneur des ajustement.
 */
void determinerScoresAjustes( const string& race, const unsigned& dext,
                              vector< int >*& ptr );

/** @brief Permet d'obtenir les scores "moyens" des talents de voleur.
 *
 * Cette fonction permet d'obtenir les scores "moyens" des talents de voleur,
 * en fonction du niveau. Ces nombres sont tirés de la table 19 du Guide du
 * Maître.
 *
 * Pour les compétences qui n'apparaissent pas dans la table 19, j'ai choisi
 * une valeur de base en me basant sur le nombre de points qu'un Voleur peut
 * dépenser. Ensuite j'ai appliqué une progression toute simple et régulière.
 *
 * @param[in] niveau niveau du PJ (dans la Classe considérée).
 * @param[out] ptr pointeur sur le conteneur des scores, est modifié ici.
 */
void obtenirScoresBase(const unsigned& niveau, vector<unsigned>*& ptr);

/** @} */

#endif
